home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / Tool Chest / Games / Game Sample Code / ZAM 1.0a13 / GameSource / TankSprite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-16  |  7.2 KB  |  326 lines  |  [TEXT/KAHL]

  1. #include "ZAMProtos.h"
  2. #include "TankSprite.h"
  3. #include "GameSounds.h"
  4. #include "SpriteFrameRates.h"
  5.  
  6. spriteLayerPtr    gTankLayer[kNumTankSprites];
  7. frameSetPtr        gTankFrameSetList[kNumDirections];
  8. spritePtr        gTankSprites[kNumTankSprites];
  9. tankInfoRec        gTankInfo[kNumTankSprites];
  10. xthing            gTankSynchTask;
  11. xthing             gTankIncidentalSoundTask;
  12.  
  13. #define kSlopTolerance 6
  14.  
  15.  
  16. long gDeadTime;
  17.  
  18. void CheckTankDead(void)
  19. /*
  20.     This is called in the main loop to kill all sounds and play the you lose sound.
  21. */
  22. {
  23.     tankInfoRec    *ti;
  24.     
  25.     if(gDead == true) {
  26.         PlaySndAsynchChannelNow(kYouLose, kMusicChan, kHighPriority+20);
  27.         gDead = false;
  28.     }
  29.     
  30. }
  31.  
  32. void TankColissionHandler( spritePtr tank, spritePtr obj, Rect *colArea)
  33. /*
  34.     The sprite manager calls this when a missile hits a tank.
  35.     This makes sure the hit was a good hit, and decrements the tank hit counter
  36. */
  37. {
  38.     tankInfoRec    *ti;
  39.     
  40.     if( (RECT_WD(*colArea) >= kCollThresh) && (RECT_HT(*colArea) >= kCollThresh) ) {
  41.         ti = (tankInfoRec*)tank->refCon;
  42.         ti->damage++;
  43.         if(ti->damage > 8) {
  44.             obj->spriteFlags |= kRemoteKilled;
  45.             ti->damage = 0;
  46.         } else
  47.             PlaySndAsynchChannel(kBadFireSnd, kFlightChan, kStdPriority);
  48.     }        
  49. }
  50.  
  51. void SynchronizeTank( gamePtr game, fixPt *loc, short direction, short speed)
  52. /*
  53.     This is where the remote tank is updated from the AppleEvent
  54. */
  55. {
  56.     spritePtr        tank;
  57.     tankInfoRec        *ti;
  58.     Boolean            reAdjustNeeded = false;
  59.     
  60.     tank = gTankSprites[game->remoteTankIndex];
  61.  
  62.     if(abs((loc->h - tank->loc.h)) > kSlopTolerance) {
  63.         reAdjustNeeded = true;
  64.     } else if(abs((loc->v - tank->loc.v)) > kSlopTolerance) {
  65.         reAdjustNeeded = true;
  66.     }
  67.     
  68.     if(reAdjustNeeded) {
  69.         tank->remoteLoc = *loc;
  70.         tank->moveTask.taskFlag = true;
  71.     }
  72.     
  73.     ti = (tankInfoRec *)tank->refCon;
  74.     if(ti->speed != speed) {
  75.         SetTankSpeed(tank, speed);
  76.     }
  77.     
  78.     if(ti->dir != direction) {
  79.         ti->dir = direction;
  80.         SetSpriteFrameSet(tank,gTankFrameSetList[ti->dir]);
  81.         tank->spriteFlags |= kNeedsToBeDrawn | kNeedsToBeErased;
  82.         tank->ownerLayer->layerFlags |= kLayerDirty;
  83.  
  84.         if( ti->speed != 0) {
  85.             DirectionToVelocity( ti->dir, &tank->vel);
  86.             if(ti->speed != 0) {
  87.                 DirectionToVelocity(ti->dir, &tank->vel);
  88.                 if(ti->speed > 1) {
  89.                     tank->vel.h = FixMul(tank->vel.h,ff(ti->speed));
  90.                     tank->vel.v = FixMul(tank->vel.v,ff(ti->speed));
  91.                 }
  92.             } else {
  93.                 tank->vel.h = 0;
  94.                 tank->vel.v = 0;
  95.             }
  96.         }
  97.     }
  98.  
  99. }
  100.  
  101.  
  102. void RotateTank(spritePtr spr, short dir)
  103. {
  104.     tankInfoRec    *tInfo;
  105.     frameCellPtr        pFrameCell;
  106.     
  107.     tInfo = (tankInfoRec*)spr->refCon;
  108.     if(dir) {
  109.  
  110.         tInfo->dir += dir;
  111.         
  112.         if(tInfo->dir >= kNumDirections) 
  113.             tInfo->dir = 0;
  114.  
  115.         if(tInfo->dir < 0) 
  116.             tInfo->dir = kNumDirections -1;
  117.  
  118.         SetSpriteFrameSet(spr,gTankFrameSetList[tInfo->dir]);
  119.         spr->spriteFlags |= kNeedsToBeDrawn | kNeedsToBeErased;
  120.         spr->ownerLayer->layerFlags |= kLayerDirty;
  121.  
  122.     }
  123. }
  124.  
  125.  
  126.  
  127. void SetTankSpeed(spritePtr spr, short speed)
  128. {
  129.     
  130.         
  131.     tankInfoRec        *tInfo;
  132.     fixPt            vel;
  133.     
  134.     tInfo = (tankInfoRec*)spr->refCon;
  135.     
  136.     tInfo->speed += speed;
  137.  
  138.     if(tInfo->speed > kMaxSpeed) 
  139.         tInfo->speed = kMaxSpeed;
  140.         
  141.     if(tInfo->speed < 0) 
  142.         tInfo->speed = 0;
  143.         
  144.     if(tInfo->speed != 0) {
  145.         DirectionToVelocity(tInfo->dir, &vel);
  146.         
  147.         spr->vel.h += vel.h;
  148.         spr->vel.v += vel.v;
  149.         
  150.     } else {
  151.         spr->vel.h = 0;
  152.         spr->vel.v = 0;
  153.     }
  154. }
  155.  
  156.  
  157. Boolean TankFrameTask(spritePtr spr, frameCellPtr curFrame)
  158. /*
  159.     Since this is a global frame task, curFrame is set to nil
  160.     if being called before the frame has been updated.
  161.     curFrame will be set to -1 if being called after the frame has already
  162.     been updated by the sprite manager.
  163. */
  164. {
  165.     short        dir = 0;
  166.     
  167.     if(KeyIsDown(kRotateLeftKeyCode))
  168.         dir = -1;
  169.     else if(KeyIsDown(kRotateRightKeyCode))
  170.         dir = 1;
  171.     
  172.     if(dir) {
  173.         RotateTank(spr, dir);
  174.     }
  175.     
  176.     return true;
  177. }
  178.  
  179. Boolean TankMoveTask(spritePtr spr)
  180. {
  181.     char            key;
  182.     short            speed = 0;
  183.     tankInfoRec        *tInfo;
  184.     short            dir= 0;
  185.  
  186.     tInfo = (tankInfoRec*)spr->refCon;
  187.     
  188.  
  189.     if(KeyIsDown(kAccelerateKeyCode))
  190.         speed = 1;
  191.     else if(KeyIsDown(kDecelerateKeyCode))
  192.         speed = -1;
  193.  
  194.     if(KeyIsDown(kFireKeyCode)) {
  195.         FireMissile( tInfo->dir, spr->loc.h, spr->loc.v, false,0);
  196.     }
  197.     
  198.     if(speed) {
  199.         SetTankSpeed(spr, speed);
  200.     }
  201.         
  202.     
  203.     
  204.     return true;
  205. }
  206.  
  207. void LoadTankSprites(gamePtr game)
  208. {
  209.     OSErr            err;
  210.     short            ref;
  211.     short            i,iconID;
  212.     frameSetPtr        missileFrameSet;
  213.         
  214.     ref = OpenResFile("\pnuTankFrames.rsrc");
  215.     if(err = ResError()) {
  216.         ErrMsgCode("\pCould Not Open MissileFrames file!.",err);
  217.         ExitToShell();
  218.     }
  219.     
  220.     if(err == noErr) {
  221.         for(i = 0; i < kNumDirections; i ++) {        
  222.             if(err == noErr) {
  223.                 iconID = kTankBaseID + i;
  224. //                err = CreateColorIconFrameSet(&gTankFrameSetList[i], iconID, kNumTankFrames);
  225.                 err = CreatePICTIconFrameSet(&gTankFrameSetList[i], iconID, kNumTankFrames);
  226.                 if(err != noErr) {
  227.                     ErrMsgCode("\pCreateColorIconFrameSet failed.",err);
  228.                 }
  229.                 if(err == noErr)
  230.                     SetFrameSetCTSeed(gTankFrameSetList[i],game->gameCTSeed);
  231.                 
  232.                 
  233.                 
  234.             }
  235.         }
  236.     }
  237.  
  238.     CloseResFile(ref);
  239.     
  240.     
  241.     for(i = 0; i < kNumTankSprites; i++) {
  242.         err = CreateSpriteLayer(&gTankLayer[i], 
  243.                             game->tween, 
  244.                             game->backdrop, 
  245.                             game->gameWind);
  246.         if(err != noErr) {
  247.             ErrMsgCode("\pCreateSpriteLayer failed!",err);
  248.             ExitToShell();
  249.         }
  250.         
  251.         err = CreateEmptySprite(gTankLayer[i],
  252.                             &gTankSprites[i],            /* returned sprite here */
  253.                             kFrameTaskBeforeUpdate        /* sprite flags */ 
  254.                             + kConstrainToRect,
  255.                             kTankFrameTime,             /* time between frame change */
  256.                             kTankMoveTime,                 /* time between movement */
  257.                             (long)&gTankInfo[i]);
  258.         
  259.         if(err != noErr) {
  260.             ErrMsgCode("\pCreateEmptySprite failed.",err);
  261.         } 
  262.         
  263.         if(err == noErr) {
  264.             err = CreateEmptyFrameSet(&gTankSprites[i]->frameList,kNumTankFrames);
  265.             if(err != noErr) {
  266.                 ErrMsgCode("\pCreateEmptyFrameSet failed.",err);
  267.             }
  268.         }
  269.         
  270.         if(err == noErr) {
  271.             SetSpriteFrameSet(gTankSprites[i],gTankFrameSetList[4]);
  272.             gTankSprites[i]->refCon = (long)&gTankInfo[i];
  273.             gTankInfo[i].dir = 4;
  274.             gTankInfo[i].speed = 0;
  275.             gTankInfo[i].game = game;
  276.             gTankInfo[i].damage = 0;
  277.             gTankSprites[i]->vel.h = 0;
  278.             gTankSprites[i]->vel.v = 0;
  279.             gTankSprites[i]->visible = true;
  280.             gTankSprites[i]->constrainRect = game->gameArea;
  281.         }
  282.     }
  283. }
  284.  
  285. void PlaceTankSprites(gamePtr game)
  286. {
  287.     register short    localIndex;
  288.     register short    remoteIndex;
  289.     tankInfoRec        *ti;
  290.     
  291.     
  292.     localIndex = game->localTankIndex;
  293.     remoteIndex = game->remoteTankIndex;
  294.     
  295.     gTankSprites[localIndex]->frameHandler = (frameProc)TankFrameTask;
  296.     gTankSprites[localIndex]->moveHandler = (moveProc)TankMoveTask;
  297.  
  298.     gTankSprites[localIndex]->spriteFlags |= kNeedsToBeDrawn | kNeedsToBeErased;
  299.     gTankLayer[localIndex]->layerFlags |= kLayerDirty;
  300.  
  301.     gTankSprites[remoteIndex]->spriteFlags |= kRemoteSprite | kRemoteUpdate 
  302.                                             | kNeedsToBeDrawn | kNeedsToBeErased;
  303.     gTankLayer[remoteIndex]->layerFlags |= kLayerDirty;
  304.  
  305.     if(game->localTankIndex == 0) {
  306.         SetSpriteLoc(gTankSprites[localIndex], ff(40), ff(100));
  307.         SetSpriteLoc(gTankSprites[remoteIndex], ff(460), ff(100));
  308.     } else {
  309.         SetSpriteLoc(gTankSprites[remoteIndex], ff(40), ff(100));
  310.         SetSpriteLoc(gTankSprites[localIndex], ff(460), ff(100));
  311.     }
  312.         
  313.     StartSpriteAction(gTankSprites[localIndex]);
  314.     gTankSprites[remoteIndex]->collideHandler = (collisionProc)TankColissionHandler;
  315.     
  316.     
  317.     
  318. #ifndef NO_NET
  319.     StartRemoteSpriteAction(gTankSprites[game->remoteTankIndex]);
  320.     StartXThing(&gTankSynchTask, kSynchTime, (updateProc)TankSynchTask, 
  321.                             (long)gTankSprites[game->localTankIndex]);
  322. #endif
  323.  
  324. }
  325.  
  326.